package com.aizuda.boot.modules.business.performancePlan.service.impl;

import com.aizuda.boot.modules.common.constant.enums.CurrencyEnum;
import com.aizuda.boot.modules.business.performancePlan.dto.*;
import com.aizuda.boot.modules.business.performancePlan.entity.CollectionPlanEntity;
import com.aizuda.boot.modules.business.performancePlan.mapper.CollectionPlanMapper;
import com.aizuda.boot.modules.business.performancePlan.service.CollectionPlanService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 收款计划 Service 实现类
 */
@Slf4j
@Service
public class CollectionPlanServiceImpl extends ServiceImpl<CollectionPlanMapper, CollectionPlanEntity> implements CollectionPlanService {

    @Override
    public List<CollectionPlanEntity> getByContractId(Integer contractId) {
        return baseMapper.selectByContractId(contractId);
    }

    @Override
    public boolean deleteByContractId(Integer contractId) {
        int deletedCount = baseMapper.deleteByContractId(contractId);
        log.info("删除合同ID为{}的收款计划，删除数量: {}", contractId, deletedCount);
        return deletedCount >= 0;
    }

    @Override
    public List<CollectionPlanEntity> getByPlanGroupId(Integer planGroupId) {
        return baseMapper.selectByPlanGroupId(planGroupId);
    }

    @Override
    public boolean updateCollectionPlan(CollectionPlanEntity collectionPlan) {
        collectionPlan.setUpdateTime(LocalDateTime.now());
        return updateById(collectionPlan);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createCollectionPlan(CreateCollectionPlanDTO createCollectionPlanDTO) {
        Integer contractId = createCollectionPlanDTO.getContractId();

        // 1. 删除当前合同ID的所有收款计划记录
        deleteByContractId(contractId);
        log.info("已删除合同ID为{}的所有收款计划记录", contractId);

        // 2. 生成新的收款计划记录
        List<CollectionPlanEntity> collectionPlanEntities = new ArrayList<>();
        AtomicInteger planGroupIdGenerator = new AtomicInteger(1);

        for (CollectionPlanGroupDTO groupDTO : createCollectionPlanDTO.getCollectionPlanGroups()) {
            // 为每个组生成自增的计划组ID（从1开始）
            Integer planGroupId = planGroupIdGenerator.getAndIncrement();

            // 为组内每个子项创建收款计划记录
            for (CollectionPlanItemDTO itemDTO : groupDTO.getChildren()) {
                CollectionPlanEntity entity = new CollectionPlanEntity();

                // 设置基本信息
                entity.setContractId(contractId);
                entity.setPlanGroupId(planGroupId);

                // 设置组级别信息（每个子项都要填充）
                entity.setIsCyclePlan(groupDTO.getIsCyclePlan());
                entity.setTotalPeriods(groupDTO.getTotalPeriods());
                entity.setFirstCollectionDate(groupDTO.getFirstCollectionDate());
                entity.setCollectionFrequency(groupDTO.getCollectionFrequency());
                entity.setCycleType(groupDTO.getCycleType());

                // 设置子项信息
                entity.setSort(itemDTO.getSort());
                entity.setFulfillmentType(itemDTO.getFulfillmentType());
                entity.setFulfillmentItem(itemDTO.getFulfillmentItem());
                entity.setCollectionTimeType(itemDTO.getCollectionTimeType());
                entity.setCollectionDate(itemDTO.getCollectionDate());
                entity.setCollectionAmount(itemDTO.getCollectionAmount());
                entity.setCurrencyType(itemDTO.getCurrencyType());
                entity.setPartnerId(itemDTO.getPartnerId());
                entity.setCollectionReceiverId(itemDTO.getCollectionReceiverId());
                entity.setCollectionReceiver(itemDTO.getCollectionReceiver());
                entity.setCollectionNote(itemDTO.getCollectionNote());
                entity.setCollectionInterval(itemDTO.getCollectionInterval());
                entity.setCollectionIntervalType(itemDTO.getCollectionIntervalType());

                // 设置时间戳
                LocalDateTime now = LocalDateTime.now();
                entity.setCreateTime(now);
                entity.setUpdateTime(now);

                collectionPlanEntities.add(entity);
            }
        }

        // 3. 批量保存收款计划
        boolean result = saveBatch(collectionPlanEntities);
        log.info("批量保存收款计划完成，合同ID: {}, 保存数量: {}, 结果: {}",
                contractId, collectionPlanEntities.size(), result);

        return result;
    }

    @Override
    public List<CollectionPlanGroupResponseDTO> getCollectionPlanDetail(Integer contractId) {
        log.info("获取收款计划详情，合同ID: {}", contractId);

        // 1. 查询所有收款计划
        List<CollectionPlanEntity> collectionPlans = getByContractId(contractId);

        if (collectionPlans.isEmpty()) {
            log.info("未找到收款计划，合同ID: {}", contractId);
            return new ArrayList<>();
        }

        // 2. 按计划组ID分组
        Map<Integer, List<CollectionPlanEntity>> groupedPlans = collectionPlans.stream()
                .collect(Collectors.groupingBy(CollectionPlanEntity::getPlanGroupId));

        // 3. 转换为响应DTO
        List<CollectionPlanGroupResponseDTO> result = groupedPlans.entrySet().stream()
                .map(entry -> {
                    Integer planGroupId = entry.getKey();
                    List<CollectionPlanEntity> plans = entry.getValue();

                    // 获取组级别信息（从第一个计划中获取）
                    CollectionPlanEntity firstPlan = plans.get(0);

                    CollectionPlanGroupResponseDTO groupDTO = new CollectionPlanGroupResponseDTO();
                    groupDTO.setPlanGroupId(planGroupId);
                    groupDTO.setIsCyclePlan(firstPlan.getIsCyclePlan());
                    groupDTO.setCollectionFrequency(firstPlan.getCollectionFrequency());
                    groupDTO.setCycleType(firstPlan.getCycleType());
                    if (firstPlan.getCycleType() != null) {
                        groupDTO.setCycleTypeDesc(firstPlan.getCycleType().getDescription());
                    }
                    groupDTO.setFirstCollectionDate(firstPlan.getFirstCollectionDate());
                    groupDTO.setTotalPeriods(firstPlan.getTotalPeriods());

                    // 转换子项
                    List<CollectionPlanDetailDTO> children = plans.stream()
                            .map(this::convertToDetailDTO)
                            .sorted((a, b) -> Integer.compare(a.getSort(), b.getSort()))
                            .collect(Collectors.toList());

                    groupDTO.setChildren(children);
                    return groupDTO;
                })
                .sorted((a, b) -> Integer.compare(a.getPlanGroupId(), b.getPlanGroupId()))
                .collect(Collectors.toList());

        log.info("获取收款计划详情成功，合同ID: {}, 计划组数量: {}, 总计划数量: {}",
                contractId, result.size(), collectionPlans.size());
        return result;
    }

    /**
     * 转换为详情DTO，包含枚举描述
     */
    private CollectionPlanDetailDTO convertToDetailDTO(CollectionPlanEntity entity) {
        CollectionPlanDetailDTO dto = new CollectionPlanDetailDTO();
        BeanUtils.copyProperties(entity, dto);

        // 设置收款时间类型描述
        if (entity.getCollectionTimeType() != null) {
            dto.setCollectionTimeTypeDesc(entity.getCollectionTimeType().getDescription());
        }

        // 设置货币类型描述
        if (entity.getCurrencyType() != null) {
            try {
                CurrencyEnum currencyEnum = CurrencyEnum.valueOf(entity.getCurrencyType());
                dto.setCurrencyTypeDesc(currencyEnum.getName());
            } catch (IllegalArgumentException e) {
                // 如果枚举中没有找到对应的货币类型，使用原值
                dto.setCurrencyTypeDesc(entity.getCurrencyType());
                log.warn("未找到货币类型枚举: {}", entity.getCurrencyType());
            }
        }

        // 设置收款间隔类型描述
        if (entity.getCollectionIntervalType() != null) {
            dto.setCollectionIntervalTypeDesc(entity.getCollectionIntervalType().getDescription());
        }

        return dto;
    }


}
